﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace NanoVirtualView
{
    public class VirtualViewRegister
    {
#pragma warning disable IDE0051 // 删除未使用的私有成员
        private static readonly int VersionInt = 1;
#pragma warning restore IDE0051 // 删除未使用的私有成员

        private List<BaseVirtualView> views = new();
        public Control Host { private set; get; }
        public event MouseEventHandler HostMouseDown;
        public event MouseEventHandler HostMouseUp;
        public event MouseEventHandler HostMouseMove;
        /// <summary>
        /// sender this
        /// </summary>
        public event MouseEventHandler HostMouseClick;
        public event MouseEventHandler HostMouseDoubleClick;
        public ContextMenuStrip ContextMenuStrip { set; get; }
        public Cursor Cursor { get => Host.Cursor; set => Host.Cursor = value; }

        public VirtualViewRegister(Control host)
        {
            Host = host;
            host.Paint += Holder_Paint;
            host.MouseDown += Holder_MouseDown;
            host.MouseUp += Holder_MouseUp;
            host.MouseMove += Holder_MouseMove;
            //holder.MouseLeave += Holder_MouseLeave;
            // holder.MouseEnter += Holder_MouseEnter;
            host.MouseClick += Holder_MouseClick;
            host.MouseDoubleClick += Holder_MouseDoubleClick;
        }

        private void Holder_MouseClick(object sender, MouseEventArgs e)
        {
            for (int i = views.Count - 1; i >= 0; i--)
            {
                if (views[i].PaintRectangle.Contains(e.Location))
                {
                    views[i].OnMouseClick(e);
                    return;
                }
            }
            HostMouseClick?.Invoke(this, e);
        }
        private void Holder_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            for (int i = views.Count - 1; i >= 0; i--)
            {
                if (views[i].PaintRectangle.Contains(e.Location))
                {
                    views[i].OnMouseDoubleClick(e);
                    return;
                }
            }
            HostMouseDoubleClick?.Invoke(this, e);
        }

        private void Holder_MouseUp(object sender, MouseEventArgs e)
        {
            for (int i = views.Count - 1; i >= 0; i--)
            {
                if (views[i].PaintRectangle.Contains(e.Location))
                {
                    views[i].OnMouseUp(e);
                    return;
                }
            }
            HostMouseUp?.Invoke(this, e);
        }

        private void Holder_MouseDown(object sender, MouseEventArgs e)
        {
            for (int i = views.Count - 1; i >= 0; i--)
            {
                if (views[i].PaintRectangle.Contains(e.Location))
                {
                    views[i].OnMouseDown(e);
                    return;
                }
            }
            HostMouseDown?.Invoke(this, e);
        }
        private void Holder_MouseMove(object sender, MouseEventArgs e)
        {
            for (int i = views.Count - 1; i >= 0; i--)
            {
                if (views[i].PaintRectangle.Contains(e.Location))
                {
                    if (views[i].Enter == true)
                    {
                        views[i].OnMouseMove(e);
                    }
                    else if (views[i].Enter == false)
                    {
                        views[i].Enter = true;
                        views[i].OnMouseEnter(e);
                    }
                    return;
                }
                else if (views[i].Enter == true)
                {
                    if (Control.MouseButtons == MouseButtons.Left)
                    {
                        views[i].OnMouseMove(e);
                        return;
                    }
                    views[i].Enter = false;
                    views[i].OnMouseLeave(e);
                }
            }
            HostMouseMove?.Invoke(this, e);
        }
        private void Holder_Paint(object sender, PaintEventArgs e)
        {
            Invalidate(e);
        }
        public void Invalidate(PaintEventArgs e)
        {
            foreach (var view in views)
            {
                if (view.Visible)
                    view.Invalidate(e);
            }
        }
        public void NotifPaint()
        {
            Host.Invalidate();
        }
        public void AddVirtualView(BaseVirtualView view)
        {
            views.Add(view);
            view.NotifPaint();
        }
        public void RemoveVirtualView(BaseVirtualView view)
        {
            views.Remove(view);
            NotifPaint();
        }
        public void RemoveAll()
        {
            views.Clear();
            NotifPaint();
        }
        public int LayoutCount => views.Count;
    }
}
